// CoreFuncs.h

#ifndef COREFUNCS_H
#define COREFUNCS_H

#include "CEGUI.h"

#include "RendererModules/Ogre/CEGUIOgreRenderer.h"

#include "OIS/OIS.h"

#include <map>

class CoreFuncs {
public:
	CoreFuncs(void *rendertarget
		, const CEGUI::String &imageset_rg
		, const CEGUI::String &fonts_rg
		, const CEGUI::String &schemes_rg
		, const CEGUI::String &looknfeels_rg
		, const CEGUI::String &layouts_rg
		, const CEGUI::String &luascripts_rg
		, const CEGUI::String &animations_rg
		, const CEGUI::String &schemas_rg);

	~CoreFuncs();

	void createImageSetFromFile(const CEGUI::String &imageset_name, CEGUI::String &filename);

	void loadImageSet(const CEGUI::String &imagesetfile_name);
	void loadFont(const CEGUI::String &fontfile_name);

	// ***** factory funcs *****

	void addListboxTextItemToCB(const CEGUI::String& cbname, const CEGUI::String& text, CEGUI::uint item_id = 0, void* item_data = 0, bool disabled = false, bool auto_delete = true);

	// ***** input interface *****

	/// should call it every frame?!
	void timePulse(float timeSinceLastFrame);

	void windowResized(float newwidth, float newheight);

	void mouseMoved(const OIS::MouseEvent &e);
	void keyPressed(const OIS::KeyEvent &e);
	void keyReleased(const OIS::KeyEvent &e);

	void mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID id);
	void mouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonID id);

	bool showMouseCursor(bool s=true);

	// GUI widget event handler utilities

	void callbackFunc(void *f) {
		callbackfunc = (bool (*)(long id, void *args)) f;
	}

	void subscribePushButtonEventClicked(const CEGUI::String &button_name, long id);
	void subscribeListBoxSelectionChanged(const CEGUI::String &listbox_name, long id);
	void subscribeCheckBoxChanged(const CEGUI::String &checkbox_name, long id);
	void subscribeRadioButtonSelectionChanged(const CEGUI::String &radiobutton_name, long id);
	void subscribeEditBoxTextAccepted(const CEGUI::String &editbox_name, long id);
	void subscribeWindowCloseClicked(const CEGUI::String &window_name, long id);

	void subscribeMouseClick(const CEGUI::String &widget_name, long id);

	void unsubscribeEvent(long id) {
		MapType::iterator iter = eventhandlers.find(id);
		if (iter != eventhandlers.end() ) {
			delete (iter->second);
			eventhandlers.erase(iter);
		}
	}

private:
	CEGUI::OgreRenderer* d_renderer;

	class EventHandler {
	public:
		EventHandler(long id_, void *dcallback_) : hid(id_) {
			dcallback = (bool (*)(long id, void *args)) dcallback_;
		}

		void connection(CEGUI::Event::Connection conn_) {
			conn = conn_;
		}

		bool eventCallback(const CEGUI::EventArgs& args) {
			return dcallback(hid,(void *)&args);
		}
		long id() const { return hid; }
	private:
		long hid;
		bool (* dcallback)(long id, void *args); 
		CEGUI::Event::Connection conn;
	};

	typedef std::map<long, EventHandler*> MapType;
	MapType eventhandlers;

	void addHandler(long id, CEGUI::EventSet& es, const CEGUI::String &name) {
		EventHandler *h = new EventHandler(id,callbackfunc);
		CEGUI::Event::Connection conn = es.subscribeEvent(name
			, CEGUI::Event::Subscriber(&EventHandler::eventCallback,h));
		h->connection(conn);
		eventhandlers[id] = h;
	}

	bool (* callbackfunc)(long id, void *args); 
};

#endif


